#ifndef  DETECTION_APP_H
#define DETECTION_APP_H

#include <opencv2/core/core.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include <queue>
#include <utility>
#include <mutex>
#include <functional>
#include <cuda_runtime.h>
#include <memory>
#include <chrono>
#include "cmw_app/work.h"
#include "detection/TensorRTWrapper/include/TrtNet.h"
#include "detection/TensorRTWrapper/include/YoloLayer.h"
#include "detection/include/dataReader.h"
#include <list>
#include <yaml-cpp/yaml.h>
using namespace std;

namespace adc
{
    class DetectionApp : public Worker
    {

    public:
        typedef  std::shared_ptr<std::list<vector<Tn::Bbox>>> OutputDataType;
        typedef  std::chrono::system_clock::time_point  TimeType;
        typedef  cv::Mat ImageType;
        typedef std::vector<std::string> ClassNameType;
        typedef std::function<void(OutputDataType&, TimeType&, ImageType&, std::vector<string>&)> DetectionCallback;
     
        DetectionApp(const std::string &config_file, const float hz);

        void SetDetectionCallback(DetectionCallback callback);
        void DoWork();

        void CacheImages(const cv::Mat &left_img, TimeType& time);

        bool ReceiveImage(void);

        vector<float> prepareImage(cv::Mat& left_img);

        void Inference();

        void DoNms(vector<Yolo::Detection> &detections, int classes, float nmsThresh);

        vector<Tn::Bbox> postProcessImg(cv::Mat& img, vector<Yolo::Detection>& detections, int classes);

        vector<string> GetNamesFromFile(string filePathAndName);

    private:
        void InitConfig(const std::string& config_file);

    private:
        std::mutex mutex_image_;
    private:
        ///cache data
        std::queue<cv::Mat> image_cache_;
        std::queue<std::chrono::system_clock::time_point> time_cache_;


    private:
        unique_ptr<Tn::trtNet> net_;
        unique_ptr<float[]> output_data_;
        shared_ptr<std::list<vector<Tn::Bbox>>> outputs_;
        cv::Mat left_image_;
        std::chrono::system_clock::time_point  current_time_;

        std::vector<string> class_name_;
        DetectionCallback detection_callback_;
	static const int kQueueSize = 10;
        int width_;
        int hight_;
        int channel_; 
        float nms_;
    };
}

#endif // ! DETECTION_APP_H
